\chapter{命令}
\section{tee}
在计算机科学中，tee是一个常见的指令，它能够将某个指令的标准输出，导向、存入某个档案中。许多不同的命令行界面（Shell）都提供这个功能，如 Unix shell、Windows PowerShell。
tee的功能通常是用管道，让它不但能在屏幕输出，而且也能够将它储存在档案中。当一个资料在被另一个指令或程式改变之前的中间输出，也能够用tee来捕捉它。tee命令能够读取标准输入，之后将它的内容写入到标准输出，同时将它的副本写入特定的档案或变量中。
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{400px-Tee.png}
\caption{tee操作流程}
\end{figure}
\subsection{使用方式}
\bashinline{tee [-a][-i][文件]}
\begin{itemize}
\item 文件一个或者多个
\item -a 追加到目标文件而不是覆盖
\item -i 忽略终端
\end{itemize}
\subsection{使用}
显示etc目录中的文件，同时写入当前目录中的etc.txt(没有的话自动创建)，同时将里面的内容的最后10行显示在屏幕上

\bashinline{ls /etc/|tee -i etc.txt |tail}

显示passwd目录，同时将目录添加当前的etc.txt文件，同时将显示的结果的最后10行输出到屏幕上，因为ls /etc/passwd命令只有一个输出，所以只显示一行。

\bashinline{ls /etc/passwd|tee -a etc.txt|tail}
\section{sed}
\subsection{set使用}
set [nefr] [动作]
\begin{itemize}
	\item n:使用silent模式。在一般的sed用法用，所有来自STDIN的数据一般都会被输出到屏幕上。然是如果加上-n后则只有经过sed处理的行(或者动作)才被列出来
	\item e:直接在指令模式下进行sed动作编辑
	\item f:直接将sed动作写入一个文件中，-f filename则可以执行filename内的sed动作
	\item r:sed的动作支持扩展型正则表达式语法而不是预设的基本正则表达式语法
\end{itemize}
动作'n1,n2 function',n1,n2不一定存在\newline
\begin{itemize}
	\item a：新增，a的后面可以接字符串，而这些字符串会选择在新的一行出现
	\item c：取代，c后面可以接字符串，这些字符串可以取代n1,n2之间的行
	\item d：删除，因为是删除后面没有接任何东西
	\item i：插入，i后面接字符串，而这些字符串在新的行出现（当前行的上一行）
	\item p：打印，将某个选择的数据输出。通常p会和参数sed -n一起
	\item s：取代，可以直接进行取代工作，通常这个s可以搭配正则表达式。
\end{itemize}
\begin{Textcode}
$ pets.txt 
This is my cat
  my cat's name is betty
This is my dog
  my dog's name is frank
This is my fish
  my fish's name is george
This is my goat
  my goat's name is adam
\end{Textcode}
1. 替换my为bleedingfight,/g表示所有的匹配项。对于特殊的符号用要用$\textbackslash$符号，比如$\textbackslash$\{,在shell中单引号原样输出字符串，双引号可以使用转义符号$\textbackslash$。

\bashinline{sed 's/my/bleedingfight/g' cat.txt}\newline
2.修改文件里面的内容。

\bashinline{sed -i 's/my/bleedingfight/g' cat.txt}\newline
或者是:
\bashinline{sed 's/my/bleedingfight/g' cat.txt > new.txt}\newline

3.在文件的每一行添加\#注释。

\bashinline{sed "s/^/#/g" cat.txt}\newline

4.在每一行的末尾加上\#。

\bashinline{sed "s/$/#/g" cat.txt}\newline

假设html.txt中的文件内容:
\begin{Textcode}
<b>This</b> is what <span style="text-decoration: underline;">I</span> meant. Understand?
\end{Textcode}
过滤<>包含的内容，

1. \bashinline{sed 's/<.*>//g' html.txt} 结果如下:
\Textinline{ meant. Understand?}

 这是因为匹配的时候匹配整个<>和其中的所有内容，然后删掉，这样就仅仅剩下空格开头的字符到结尾了。

2.\bashinline{sed 's/<[^>]*>//g' html.txt}结果如下:

\bashinline{sed 's/<[^>]*>//g' html.txt}

\Textinline{This is what I meant. Understand?}

指定替换的内容:
1.替换第1-3行内容my为bleedingfight

\bashinline{sed "1,3s/my/bleedingfight/g" cat.txt}\newline 
2.只替换每行第一个s为S

\bashinline{sed "1,3s/s/S/1" cat.txt}\newline
\begin{Textcode}
ThiS is my cat
  my cat'S name is betty
ThiS is my dog
  my dog's name is frank
This is my fish
  my fish's name is george
This is my goat
  my goat's name is adam 
\end{Textcode}
3.只替换每行第二个s为S

\bashinline{sed "1,3s/s/S/2" cat.txt}\newline

\begin{Textcode}
This iS my cat
  my cat's name iS betty
This iS my dog
  my dog's name is frank
This is my fish
  my fish's name is george
This is my goat
  my goat's name is adam 
\end{Textcode}
4.替换每行第3个以后的所有s为S

\bashinline{sed "s/s/S/3g" cat}

\begin{Textcode}
This is my cat
  my cat's name is betty
This is my dog
  my dog's name is frank
This is my fish
  my fish's name is george
This is my goat
  my goat's name is adam 
\end{Textcode}
替换命令在替换多行文本时能正常工作，但是默认情况下它值替换每行中出现的第一处。要让替换命令能够替换一行中不同地方出现的文本必须使用替换标记。替换标记会替换命令字符串之后的设置。\\*
\bashinline{s/pattern/replacement/flags}\\*
下面有4中可用的替换标记:
\begin{itemize}
\item 数字，表明新文本将替换第几处模式匹配的地方
\item g,表示新文本将会替换所有匹配的文本
\item p,表明原先行的内容要打印出来
\item w file,将替换的结果写到文件中
\end{itemize}
下面的命令替换test.txt中的内容test为trail同时将输出保存在data.txt\\*
\bashinline{sed 's/test/trail/w test.txt' data.txt}\\*
在使用sed替换的时候，反斜线$\textbackslash$ 会被当做特殊字符，这时候需要替换的时候需要转义反斜线，使用/$\textbackslash$转义。\\*
\bashinline{sed -n 's/\/bin\/bash/\/bin\/csh/p' /etc/passwd}\\*
sed可以使用其他的分隔符替代$\textbackslash$,替换后$\textbackslash$就不在是分隔符，这时候就可以将$\textbackslash$作为元素替换了。下面将!用作分隔符分割。\\*
\bashinline{sed -n 's!/bin/bash!/bin/csh!p' /etc/passwd}
把第1-3行的my替换为bleedingfight，第3行以后的This替换为That

\bashinline{sed -e '1,3s/my/bleedingfight/g' -e '3,$s/This/That/g' cat.txt}\newline
\&可以当做匹配的字符串使用,下面将my替换为my's:

\bashinline{sed "s/my/&'s/g" cat.txt}\newline
N目录：把下一行的内容当成缓冲区做匹配。下面的例子把原文中偶数行纳入奇数行匹配，而s只匹配第一个。
\begin{Textcode}
$ sed "N;s/my/bleedingfight/" cat.txt
This is bleedingfight cat
  my cat's name is betty
This is bleedingfight dog
  my dog's name is frank
This is bleedingfight fish
  my fish's name is george
This is bleedingfight goat
  my goat's name is adam 
\end{Textcode}
这里的偶数行中的my没有匹配，因为偶数行纳入奇数行，在奇数行中属于第二个my。
i命令，在制定位置插入。在第一行前添加内容:
\begin{Textcode}
$sed "1 i # This is a annotation" cat.txt
# This is a annotation
This is my cat
  my cat's name is betty
This is my dog
  my dog's name is frank
This is my fish
  my fish's name is george
This is my goat
  my goat's name is adam
\end{Textcode}

在最后一行追加一行
\begin{Textcode}
$ sed "$ a  # This is a annotation" cat.txt
This is my cat
  my cat's name is betty
This is my dog
  my dog's name is frank
This is my fish
  my fish's name is george
This is my goat
  my goat's name is adam

# This is a annotation

\end{Textcode}
找到fish所在行，在它所在行后一行添加内容
\begin{Textcode}
$ sed "/fish/a  # 添加到fish行后的内容" cat.txt
This is my cat
  my cat's name is betty
This is my dog
  my dog's name is frank
This is my fish
# 添加到fish行后的内容
  my fish's name is george
# 添加到fish行后的内容
This is my goat
  my goat's name is adam 
\end{Textcode}
c命令：替换匹配行
\begin{Textcode}

ed "2 c  # 第二行的内容" cat.txt
This is my cat
# 第二行的内容
This is my dog
  my dog's name is frank
This is my fish
  my fish's name is george
This is my goat
  my goat's name is adam
\end{Textcode}
找到fish所在行替换为“fish行变成了FISH”
\begin{Textcode}
$ sed "/fish/c  fish行变成了FISH" cat.txt
This is my cat
  my cat's name is betty
This is my dog
  my dog's name is frank
fish行变成了FISH
fish行变成了FISH
This is my goat
  my goat's name is adam 
\end{Textcode}
d命令，\textcolor{red}{删除}。
1. 删除fish所在行。
\begin{Textcode}
$ sed "/fish/d" cat.txt
This is my cat
  my cat's name is betty
This is my dog
  my dog's name is frank
This is my goat
  my goat's name is adam 
\end{Textcode}
2.删除第2-4行
\begin{Textcode}
$ sed "2,4d" cat.txt
This is my cat
This is my fish
  my fish's name is george
This is my goat
  my goat's name is adam 
\end{Textcode}
p命令：打印。
1.打印fish所在行，这里加入参数-n为了显示仅仅sed处理的行，而不是全部内容，这样fish所在行就不会因此输出两遍。
\begin{Textcode}
$ sed -n "/fish/p" cat.txt
This is my fish
  my fish's name is george 
\end{Textcode}
2.打印dog和fish所在行内容。
\begin{Textcode}
$ sed -n "/dog/,/fish/p" cat.txt 
This is my dog
  my dog's name is frank
This is my fish 
\end{Textcode}
打包命令，删除第3行到6行中有This的行:
\begin{Textcode}
$sed   "3,6 {/This/d}" cat.txt 
This is my cat
  my cat's name is betty
  my dog's name is frank
  my fish's name is george
This is my goat
  my goat's name is adam 
\end{Textcode}
找到This所在行然后在找该行中的fish，然后在删除。
\begin{Textcode}
$ sed   "3,6 {/This/{/fish/d}}" cat.txt 
This is my cat
  my cat's name is betty
This is my dog
  my dog's name is frank
  my fish's name is george
This is my goat
  my goat's name is adam 
\end{Textcode}
从第一行到最后一行，如果匹配到This，则删除；如果前面有空格，则删除空格
\begin{Textcode}
$ sed '1,${/This/d;s/^ *//g}' cat.txt
my cat's name is betty
my dog's name is frank
my fish's name is george
my goat's name is adam
\end{Textcode}
\subsection{Hold Space}

第三个我们再来看一下 Hold Space

接下来，我们需要了解一下Hold Space的概念，我们先来看四个命令：
\begin{itemize}
\item g： 将hold space中的内容拷贝到pattern space中，原来pattern space里的内容清除
\item G： 将hold space中的内容append到pattern space$\textbackslash$n后
\item h： 将pattern space中的内容拷贝到hold space中，原来的hold space里的内容被清除
\item H： 将pattern space中的内容append到hold space$\textbackslash$n后
\item x： 交换pattern space和hold space的内容
\end{itemize}
假设文件t中的内容:
\begin{Textcode}
$ cat t.txt
one
two
three 
\end{Textcode}
第一个示例
\begin{Textcode}
$ sed 'H;g' t.txt
one
 
one
two
 
one
two
three
\end{Textcode}
是不是有点没看懂，我作个图你就看懂了。
\begin{figure}[H]
\centering
\includegraphics[scale=0.5]{sed_demo_00.jpg}
\caption{}
\end{figure}
第二个示例，反序了一个文件的行：
\begin{Textcode}
1
2
3
4
$ sed '1!G;h;$!d' t.txt
three
two
one
\end{Textcode}
其中的 ‘1!G;h;\$!d’ 可拆解为三个命令

1!G —— 只有第一行不执行G命令，将hold space中的内容append回到pattern space
h —— 第一行都执行h命令，将pattern space中的内容拷贝到hold space中
\$!d —— 除了最后一行不执行d命令，其它行都执行d命令，删除当前行
这个执行序列很难理解，做个图如下大家就明白了：
\begin{figure}[H]
\centering
\includegraphics[scale=0.5]{sed_demo.jpg}
\caption{处理过程}
\end{figure}








\section{正则表达式}
\begin{itemize}
	\item \^{} 表示一行的开头。\^{} \#表示以\#开头
\item \$i 表示一行结尾。\}\$表示以\}结尾
\item $\textbackslash<$ 表示词首。如：$\textbackslash$<abc表示以abc为首的词
\item $\textbackslash>$ 表示词首。如：$abc\textbackslash$表示以abc为结尾的词
\item . 表示任何一个单个字符
\item * 表示某个字符出现了0次或者多次
\item []字符集合，如[abc]表示a或者b或者c。[a-zA-Z]表示所有字母，[\^{}表示非a字母]
\end{itemize}

\section{awk}
\begin{itemize}
\item -F fs or --field-separator fs 指定输入文件折分隔符，fs是一个字符串或者是一个正则表达式，如-F:。
\item -v var=value or --asign var=value  赋值一个用户定义变量。
\item -f scripfile or --file scriptfile  从脚本文件中读取awk命令。
\item -mf nnn and -mr nnn 对nnn值设置内在限制，-mf选项限制分配给nnn的最大块数目；-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能，在标准awk中不适用。
\item -W compact or --compat, -W traditional or --traditional  在兼容模式下运行awk。所以gawk的行为和标准的awk完全一样，所有的awk扩展都被忽略。
\item -W copyleft or --copyleft, -W copyright or --copyright 打印简短的版权信息。
\item -W help or --help, -W usage or --usage  打印全部awk选项和每个选项的简短说明。
\item -W lint or --lint  打印不能向传统unix平台移植的结构的警告。
\item -W lint-old or --lint-old  打印关于不能向传统unix平台移植的结构的警告。
\item -W posix 打开兼容模式。但有以下限制，不识别：/x、函数关键字、func、换码序列以及当fs是一个空格时，将新行作为一个域分隔符；操作符**和**=不能代替\^和\^=；fflush无效。
\item -W re-interval or --re-inerval 允许间隔正则表达式的使用，参考(grep中的Posix字符类)，如括号表达式[[:alpha:]]。
\item -W source program-text or --source program-text  使用program-text作为源代码，可与-f命令混用。
\item -W version or --version 打印bug报告信息的版本。
\end{itemize}
\section{gawk}
\begin{table}[H]
\centering
\begin{tabular}{cc}
选项&描述\\
-F fs&指定行中划分数据字段的字段分隔符\\
-f file&从指定文件中读取程序\\
-v var=value&定义gawk程序中的一个变量及其默认值\\
-mf N&指定要处理的数据文件中的最大字段数\\
-mr N&指定数据文件中的最大数据行数\\
-W keyword&指定gawk的兼容模式或警告等级
\end{tabular}
\end{table}
gawk程序脚本使用一对花括号定义。必须将脚本命令放在花括号(\{\})中。
\begin{gawk}
gawk '{print "Hello world"}'
\end{gawk}
这里外层的单引号因为gawk将脚本当做单个文本字符串，你必须将脚本放在单引号中。这里定义了一个命令print。执行这条命令什么都不会发生。原因在于没有在命令行上指定文件名，所以gawk程序会重STDIN接收数据。在运行这个程序的时候，它会一直等待从STDIN输入的文本。如果你输入一行文本并按下回车，gawk会对该文本执行一遍程序脚本。由于程序脚本用来显示固定的字符串，因此不管你在数据流中输入什么文本，都会得到同样的输出“hello world”。
要终止gawk程序，你必须表明数据流已经结束了。bash shell提供了一个租个见用了生成EOF（END OF FILE）字符。Ctrl+D组合件会在bash中产生一个EOF。这个组合件能终止该gawk程序并返回到命令行界面提示符下。
\subsection{使用数据字段变量}
\begin{itemize}
\item \$0 表示整个文本行
\item \$1 代表文本行中的第一个数据字段
\item \$2 代表文本行中第二个数据字段
\item \$n 代表文本行中第n个数据字段
\end{itemize}
假设文本文件test.txt的内容如下:
\begin{bash}
One line of test text.
Two line of test text.
Three line of test text.
\end{bash}
打印文件的第一行:
\begin{gawk}
gawk '{print $1}' test.txt 
\end{gawk}
输出结果如下:
\begin{bash}
line
line
line
\end{bash}
这里处理的时候对于每一行将他们以空格分隔，分割后的第1位\$1表示第一个元素，这里为第一个元素。总共三行每行都这样处理。如果你想使用其他的分隔符可以通过参数F指定:
下面我们使用 : 作为分隔符，获取/etc/passwd文件中的用户名称:
\begin{gawk}
gawk -F: '{print $1}' /etc/passwd
\end{gawk}
\subsection{在脚本中使用多个命令}
gawk允许你将多条awk语句组合成一个正常的程序。要在命令行上的程序脚本中使用多条命令只需要在命令之间加上分号分隔即可。
下面的命令将第四个字段用“christine”替换然后输出整个文本行。\\*
\gawkinline{echo "My name is Rich"|awk '{$4="christine";print $0}'}
\subsection{从文件中读取程序}
这里的'test.gawk'里面的内容如下:\\*
\gawkinline{print $1 "'s home directory is "$6}\\*
\gawkinline{gawk F: -f test.gawk /etc/passwd}
显示用户的当前目录。gawk文件也可以这样指定\\*
\begin{gawk}
{
text = "'s home directory is "
print $1 text $6
}
\end{gawk}
gawk定变量来处理文件，这里的变量不需要美元符号来引用。
\subsection{在处理数据前运行脚本}
默认情况下，gawk会从输入中读取一行文本，然后针对该行的数据执行程序脚本。有时可能需要在处理数据前运行脚本，比如为报告创建标题。BEGIN关键字就是用来做这个的。\\*
\gawkinline{gawk 'BEGIN {print "Hello World"}'}\\*
这里print命令会在读取数据前显示文本。但是在他显示之后，它会迅速推出，不等待任何数据，如果想使用正常的程序脚本处理数据，必须用顶一个脚本区域定义程序。

下面的脚本显示一行字符串后打印godemo.go文件里面的内容。\\*
\gawkinline{gawk 'BEGIN {print "The data3 File Contents: "};{print $0}' godemo.go}
\subsection{数据处理后执行脚本}
开始处理数据前打印Start processing data，处理完成后打印Processed。
\begin{gawk}
gawk 'BEGIN {print "Start processing data"};END {print "Processed "}' godemo.go
\end{gawk}
\section{crontab}
crontab命令被用来提交和管理用户的需要周期性执行的任务，与windows下的计划任务类似，当安装完成操作系统后，默认会安装此服务工具，并且会自动启动crond进程，crond进程每分钟会定期检查是否有要执行的任务，如果有要执行的任务，则自动执行该任务。

\textbf{语法}
crontab(选项)(参数)\\*
\begin{itemize}
\item[-e]：编辑该用户的计时器设置；
\item[-l]：列出该用户的计时器设置；
\item[-r]：删除该用户的计时器设置；
\item[-u]<用户名称>：指定要设定计时器的用户名称。
\end{itemize}
参数\\*
crontab文件：指定包含待执行任务的crontab文件。\\*
\textbf{知识扩展}
Linux下的任务调度分为两类：系统任务调度和用户任务调度。

系统任务调度：系统周期性所要执行的工作，比如写缓存数据到硬盘、日志清理等。在/etc目录下有一个crontab文件，这个就是系统任务调度的配置文件。

/etc/crontab文件包括下面几行：
\begin{bash}
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=""HOME=/

# run-parts
51 * * * * root run-parts /etc/cron.hourly
24 7 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly
\end{bash}
前四行是用来配置crond任务运行的环境变量。\\
第一行SHELL变量指定了系统要使用哪个shell，这里是bash。\\
第二行PATH变量指定了系统执行命令的路径。\\
第三行MAILTO变量指定了crond的任务执行信息将通过电子邮件发送给root用户，如果MAILTO变量的值为空，则表示不发送任务执行信息给用户。\\
第四行的HOME变量指定了在执行命令或者脚本时使用的主目录。\\
用户任务调度：用户定期要执行的工作，比如用户数据备份、定时邮件提醒等。用户可以使用 crontab 工具来定制自己的计划任务。所有用户定义的crontab文件都被保存在/var/spool/cron目录中。其文件名与用户名一致，使用者权限文件如下：
\begin{itemize}
\item /etc/cron.deny     该文件中所列用户不允许使用crontab命令
\item /etc/cron.allow    该文件中所列用户允许使用crontab命令
\item /var/spool/cron/   所有用户crontab文件存放的目录,以用户名命名
\end{itemize}
crontab文件的含义：用户所建立的crontab文件中，每一行都代表一项任务，每行的每个字段代表一项设置，它的格式共分为六个字段，前五段是时间设定段，第六段是要执行的命令段，格式：\bashinline{minute   hour   day   month   week   command}。\\
\begin{itemize}
\item  minute： 表示分钟，可以是从0到59之间的任何整数。
\item  hour：表示小时，可以是从0到23之间的任何整数。
\item  day：表示日期，可以是从1到31之间的任何整数。
\item  month：表示月份，可以是从1到12之间的任何整数。
\item  week：表示星期几，可以是从0到7之间的任何整数，这里的0或7代表星期日。
\item command：要执行的命令，可以是系统命令，也可以是自己编写的脚本文件。
\end{itemize}
在以上各个字段中，还可以使用以下特殊字符：
\begin{itemize}
\item 星号（*）：代表所有可能的值，例如month字段如果是星号，则表示在满足其它字段的制约条件后每月都执行该命令操作。
\item 逗号（,）：可以用逗号隔开的值指定一个列表范围，例如，“1,2,5,7,8,9”
\item 中杠（-）：可以用整数之间的中杠表示一个整数范围，例如“2-6”表示“2,3,4,5,6”
\item 正斜线（/）：可以用正斜线指定时间的间隔频率，例如“0-23/2”表示每两小时执行一次。同时正斜线可以和星号一起使用，例如*/10，如果用在minute字段，表示每十分钟执行一次。
\end{itemize}
\textbf{crond服务}
\begin{itemize}
\item /sbin/service crond start    //启动服务
\item /sbin/service crond stop     //关闭服务
\item /sbin/service crond restart  //重启服务
\item /sbin/service crond reload   //重新载入配置
\end{itemize}
\textbf{查看crontab服务状态：}

\bashinline{service crond status}
\begin{bash}
● crond.service
Loaded: not-found (Reason: No such file or directory)
Active: inactive (dead)
\end{bash}
手动启动crontab服务：

\bashinline{service crond start}

加入开机自动启动：
\bashinline{chkconfig –level 35 crond on}
\subsection{实例}
每1分钟执行一次command：\bashinline{* * * * * command}

每小时的第3和第15分钟执行：\bashinline{3,15 * * * * command}

在上午8点到11点的第3和第15分钟执行：\bashinline{3,15 8-11 * * * command}

每隔两天的上午8点到11点的第3和第15分钟执行：\bashinline{3,15 8-11 */2 * * command}

每个星期一的上午8点到11点的第3和第15分钟执行：\bashinline{3,15 8-11 * * 1 command}

每晚的21:30重启smb :\bashinline{30 21 * * * /etc/init.d/smb restart}

每月1、10、22日的4 : 45重启smb： \bashinline{45 4 1,10,22 * * /etc/init.d/smb restart}

每周六、周日的1:10重启smb：\bashinline{10 1 * * 6,0 /etc/init.d/smb restart}

每天18 : 00至23 : 00之间每隔30分钟重启smb：\bashinline{0,30 18-23 * * * /etc/init.d/smb restart}

每星期六的晚上11:00 pm重启smb ：\bashinline{0 23 * * 6 /etc/init.d/smb restart}

每一小时重启smb ：\bashinline{* */1 * * * /etc/init.d/smb restart}

晚上11点到早上7点之间，每隔一小时重启smb：\bashinline{* 23-7/1 * * * /etc/init.d/smb restart}

每月的4号与每周一到周三的11点重启smb ：\bashinline{0 11 4 * mon-wed /etc/init.d/smb restart}

一月一号的4点重启smb：\bashinline{0 4 1 jan * /etc/init.d/smb restart}

每小时执行/etc/cron.hourly目录内的脚本：\bashinline{01 * * * * root run-parts /etc/cron.hourly}
\section{tmux}
tmux new -s myname 可以指定Session名
根据tmux的定义，在开启了tmux服务器后，会首先创建一个会话，而这个会话则会首先创建一个窗口，其中仅包含一个面板；也就是说，这里看到的所谓终端控制台应该称作tmux的一个面板，虽然其使用方法与终端控制台完全相同。tmux使用C/S模型构建，主要包括以下单元模块：
\begin{itemize}
\item server服务器。输入tmux命令时就开启了一个服务器。
\item session会话。一个服务器可以包含多个会话
\item window窗口。一个会话可以包含多个窗口。
\item pane面板。一个窗口可以包含多个面板。
\end{itemize}
\begin{itemize}
\item tmux new -s 会话名称:在tmux中创建一个会话
\item tmux attach-session -t myname:重新连接此myname会话
\item tmux attach:打开后台的tmux会话
\item tmux a -t basic
\item tmux list-session:列出当前会话
\item tmux ls:列出当前会话
\item [PREFIX-s]\footnote{PREFIX表示ctrl+b通常改为ctrl+a} 在tmux中查看会话列表并切换（这条命令表示ctrl+a+s）
\item tmux new-session <会话名>
\item tmux attach-session -t <会话名>
\item tmux rename-session -t <会话名>
\item tmux choose-session -t <会话名>
\item tmux kill-session -t <会话名>
\end{itemize}
\subsection{快捷键}
\begin{itemize}
\item[PREFIX+\$] 重命名当前Session
\item[PREFIX+d] detach 分离会话
\item[PREFIX+t] 时钟
\item[PREFIX+?] list shortcuts
\item[PREFIX+:] 命令模式。
\end{itemize}
\subsection{分割终端窗口}
\begin{itemize}
\item [PREFIX+ ”] 在光标当前所在窗口，横向分割出一个窗口
\item [PREFIX+ \%] 在光标当前所在窗口，竖向分割出一个窗口
\item [PREFIX+ !] 关闭所有分割出来的窗口
\item [PREFIX+ x] 关闭光标当前所在窗口。(或直接Ctrl+d)
\item [PREFIX+ \{] 向前置换当前面板
\item [PREFIX+ \}] 向后置换当前面板
\item [PREFIX+ q] 查询面板编号
\end{itemize}
\subsection{使用不同的窗口工作}
一个终端里开了多个小窗口，还是不够用？ctrl+b(默认，通常修改为ctrl+a)
\begin{itemize}
\item[PREFIX + c] 创建一个新的窗口(全屏)
\item[PREFIX + p] 切换到上一个窗口
\item[PREFIX + n] 切换到下一个窗口
\item[PREFIX + f] 列出所有窗口
\item[PREFIX + w] 列出目前所创建的窗口,能看到窗口编号,在按编号直接切换窗口
\item[PREFIX + 0-9] 直接切换到指定编号的窗口
\item[PREFIX + , ]修改当前窗口名字,见图3
\item[PREFIX + d ]临时断开所有的会话，用命令\# tmux attach 恢复会话
\item[PREFIX + \& ]关闭窗口之前，你需要确认一下
\end{itemize}
\subsection{调整pane大小}
\begin{itemize}
\item[PREFIX-z] trigger暂时把窗口变大
\end{itemize}
\subsection{关闭及移动}
\begin{itemize}
\item[PREFIX-x] 关闭当前pane, 需确认
\item[PREFIX-\}] 当前pane移到左边
\item[PREFIX-\{] 当前pane移到右边
\end{itemize}
\subsection{复制粘贴}
\begin{itemize}
\item[PREFIX-[] 进入复制模式
\item[=>] 可以进行的操作
\item[space/v] 开始选择
\item[Ctrl-v] 整块选择
\item[hjkl] 方向键移动
\item[w/b] 向前向后移动一个单词
\item[fx/Fx] 行内移动到下一个字符位置
\item[ctrl-b/f] 在缓冲区里面翻页
\item[g/G] 到缓冲区最顶/底端
\item[/ ?] 向下, 向上查找
\item[n/N] 查找后下一个, 上一个
\item[Enter/y] 复制
\item[PREFIX-]] 粘贴
\item[PREFIX-:] 复制整个pane可见区域
\item[PREFIX-:] 查看缓冲区内容
\item[PREFIX-:] 列出缓冲区列表
\item[PREFIX-:] choose-buffer => 回车 从缓冲区列表选择并插入到当期面板
\end{itemize}
\subsection{处理多窗口}
 有时候你在编辑器工作的同时，需要查看日志文件。在编辑的同时追踪日志真的很有帮助。Tmux可以让我们把窗口分成许多面板。举个例子，我们可以创建一个控制台监测我们的服务器，同时用编辑器构造复杂的开发环境，这样就能同时进行编译和调试了。tmux new -s panes(创建面板panes)
\begin{itemize}
\item[PREFIX + ”] 水平分割一个窗口 原来的
\item[PREFIX + \%]再竖直分割 原来的
\item[PREFIX + 方向键] 在他们之间移动
\item[PREFIX 按住不放]再按方向键，可以实现panes之间大小的改变
\item[PREFIX o ]切换面板
\item[PREFIX q ]显示面板号
\item[PREFIX x]杀掉面板
\item[PREFIX space]:切换面板布局
\item[PREFIX z] 缩放面板
\end{itemize}
\textbf{常见问题}
在终端窗口里复制 在一个终端里分割了多个小窗口，你可能会在一个小窗口里复制一些代码或命令行到另外一个小窗口，这时你用小红点、鼠标、触摸板是无法胜任的。它把整个终端窗口当作是复制区域对象,而不隔离小窗口复制
\begin{itemize}
\item[[] 进入复制模式，移动光标到要复制文本区域后，按空格键开始选择要复制的内容, 利用h、j、k、l、\$、0等(和vim中操作一样)，按回车确认选中的内容。
\item []] 粘贴
\item 上面所介绍的是一些比较实用的功能，使用熟练在于 vim 的熟练应用. (控制键的快捷键按键组合方式：Ctrl+b前面也说过弊处，后来换成Ctrl+n发现在终端中不能向下翻命令，在改成Ctrl+m后，发现回车也用不了了。直接算了
\item tmux clear-history)
\end{itemize}
\textbf{使用常见的tmux配置文件}
\begin{bash}
cd
rm -rf .tmux
git clone https://github.com/gpakosz/.tmux.git
ln -s .tmux/.tmux.conf
cp .tmux/.tmux.conf.local 
\end{bash}
生成配置文件\bashinline{touch ~/.tmux.conf}
配置完以后，重启tmux起效，或者先按C+b，然后输入：，进入命令行模式，在命令行模式下输入：
\bashinline{source-file ~/.tmux.conf}
你也可以跟我一样，在配置文件中加入下面这句话，以后改了只需要按前缀+r了。
将r 设置为加载配置文件，并显示”reloaded!”信息
\section{xargs}
在工作中经常会接触到xargs命令，特别是在别人写的脚本里面也经常会遇到，但是却很容易与管道搞混淆，本篇会详细讲解到底什么是xargs命令，为什么要用xargs命令以及与管道的区别。

为什么要用xargs呢，我们知道，linux命令可以从两个地方读取要处理的内容，一个是通过命令行参数，一个是标准输入。例如cat、grep就是这样的命令，举个例子：\\*
\bashinline{echo 'main' | cat test.cpp}\\
这种情况下cat会输出test.cpp的内容，而不是'main'字符串，如果test.cpp不存在则cat命令报告该文件不存在，并不会尝试从标准输入中读取。\bashinline{echo 'main'} | 会通过管道将 echo 的标准输出(也就是字符串'main')导入到 cat 的标准输入，也就是说此时cat的标准输入中是有内容的，其内容就是字符串'main'但是上面的内容中cat不会从它的标准输入中读入要处理的内容。(注:标准输入是有一个缓冲区的，就像我们在程序中使用scanf函数从标准输入中读取一样，实际上是从标准输入的缓冲区中读取的)。其实基本上linux的命令中很多的命令的设计是先从命令行参数中获取参数，然后从标准输入中读取，反映在程序上，命令行参数是通过main函数 \cppinline{int main(int argc,char*argv[])} 的函数参数获得的，而标准输入则是通过标准输入函数例如C语言中的scanf读取到的。他们获取的地方是不一样的。例如：\bashinline{echo 'main' | cat}
这条命令中cat会从其标准输入中读取内容并处理，也就是会输出 'main' 字符串。echo命令将其标准输出的内容 'main' 通过管道定向到 cat 的标准输入中。
\bashinline{cat}
如果仅仅输入cat并回车，则该程序会等待输入，我们需要从键盘输入要处理的内容给cat，此时cat也是从标准输入中得到要处理的内容的，因为我们的cat命令行中也没有指定要处理的文件名。大多数命令有一个参数  -  如果直接在命令的最后指定 -  则表示从标准输入中读取，例如：\\
\bashinline{echo 'main' | cat -}
这样也是可行的，会显示 'main' 字符串，同样输入 cat - 直接回车与输入 cat 直接回车的效果也一样，但是如果这样呢：

\bashinline{echo 'main' | cat test.cpp -}

同时指定test.cpp 和 - 参数，此时cat程序还是会显示test.cpp的内容。但是有一个程序的策略则不同，它是grep，例如：\\
\bashinline{echo 'main' | grep 'main' test.cpp -}
该命令的输出结果是:
\begin{bash}
test.cpp:int main()
(standard input):main
\end{bash}

此时grep会同时处理标准输入和文件test.cpp中的内容，也就是说会在标准输入中搜索 'main' 也会在文件 test.cpp (该文件名从grep命令行参数中获得)中搜索 'main'。也就是说当命令行中 test.cpp 和 - 两个参数同时存在的时候，不同的程序处理不同。我们看到了cat与grep处理就不同。但是有一点是一样的，首先在命令行中查找要处理的内容的来源(是从文件还是从标准输入，还是都有)，如果在命令行中找不到与要处理的内容的来源相关的参数则默认从标准输入中读取要处理的内容了。

另外很多程序是不处理标准输入的，例如 kill , rm 这些程序如果命令行参数中没有指定要处理的内容则不会默认从标准输入中读取。所以：

\bashinline{echo '516' | kill}\\*
这种命里是不能执行的。

\bashinline{echo 'test' | rm -f}\\*
这种也是没有效果的。

这两个命令只接受命令行参数中指定的处理内容，不从标准输入中获取处理内容。想想也很正常，kill 是结束进程，rm是删除文件，如果要结束的进程pid和要删除的文件名需要从标准输入中读取，这个也很怪异吧。 但是像 cat与grep这些文字处理工具从标准输入中读取待处理的内容则很自然。

但是有时候我们的脚本却需要 echo '516' | kill 这样的效果，例如 ps -ef | grep 'ddd' | kill 这样的效果，筛选出符合某条件的进程pid然后结束。这种需求对于我们来说是理所当然而且是很常见的，那么应该怎样达到这样的效果呢。有几个解决办法：

1. 通过 \bashinline{kill `ps -ef | grep 'ddd'` }
\#这种形式，这个时候实际上等同于拼接字符串得到的命令，其效果类似于  \bashinline{kill $pid}

2. \begin{bash}
    for procid in $(ps -aux | grep "some search" | awk '{print $2}');
        do kill -9 $procid; 
    done 
\end{bash}
这种方式其实与第一种原理一样，只不过需要多次kill的时候是循环处理的，每次处理一个

3. \bashinline{ps -ef | grep 'ddd' | xargs kill  }\\
OK，使用了xargs命令，铺垫了这么久终于铺到了主题上。

xargs命令可以通过管道接受字符串，并将接收到的字符串通过空格分割成许多参数(默认情况下是通过空格分割) 然后将参数传递给其后面的命令，作为后面命令的命令行参数

xargs是什么，与管道有什么不同xargs与管道有什么不同呢?这是两个很容易混淆的东西，看了上面的xargs的例子还是有点云里雾里的话，我们来看下面的例子弄清楚为什么需要xargs：

\bashinline{echo '--help' | cat }
输出：--help

\bashinline{echo '--help' | xargs cat }
输出（实质上相当于cat --help）：
\begin{bash}
Usage: cat [OPTION]... [FILE]...
Concatenate FILE(s), or standard input, to standard output.
 
  -A, --show-all           equivalent to -vET
  -b, --number-nonblank    number nonempty output lines
  -e                       equivalent to -vE
  -E, --show-ends          display $ at end of each line
  -n, --number             number all output lines
  -s, --squeeze-blank      suppress repeated empty output lines
  -t                       equivalent to -vT
  -T, --show-tabs          display TAB characters as ^I
  -u                       (ignored)
  -v, --show-nonprinting   use ^ and M- notation, except for LFD and TAB
      --help     display this help and exit
      --version  output version information and exit
 
With no FILE, or when FILE is -, read standard input.
 
Examples:
  cat f - g  Output f's contents, then standard input, then g's contents.
  cat        Copy standard input to standard output.
 
Report cat bugs to bug-coreutils@gnu.org
GNU coreutils home page: <http://www.gnu.org/software/coreutils/>
General help using GNU software: <http://www.gnu.org/gethelp/>
For complete documentation, run: info coreutils 'cat invocation'
\end{bash}

可以看到 \bashinline{echo '--help' | cat}  该命令输出的是echo的内容，也就是说将echo的内容当作cat处理的文件内容了，实际上就是echo命令的输出通过管道定向到cat的输入了。然后cat从其标准输入中读取待处理的文本内容。这等价于在test.txt文件中有一行字符 '--help' 然后运行  cat test.txt 的效果。

而 \bashinline{echo '--help' | xargs cat} 等价于 cat --help。 什么意思呢？就是xargs将其接受的字符串 --help 做成cat的一个命令参数来运行cat命令，同样\\  \bashinline{echo 'test.c test.cpp' | xargs cat }等价于 \bashinline{cat test.c test.cpp} 此时会将test.c和test.cpp的内容都显示出来。

回到顶部
xargs的一些有用的选项
相信到这里应该都知道xargs的作用了，那么我们看看xargs还有一些有用的选项：

1. -d 选项
默认情况下xargs将其标准输入中的内容以空白(包括空格、Tab、回车换行等)分割成多个之后当作命令行参数传递给其后面的命令，并运行之，我们可以使用 -d 命令指定分隔符，例如：
\bashinline{echo '11@22@33' | xargs echo }
输出：11@22@33。
默认情况下以空白分割，那么11@22@33这个字符串中没有空白，所以实际上等价于 echo 11@22@33 其中字符串 '11@22@33' 被当作echo命令的一个命令行参数

\bashinline{echo '11@22@33' | xargs -d '@' echo }
输出：
11 22 33
指定以@符号分割参数，所以等价于 echo 11 22 33 相当于给echo传递了3个参数，分别是11、22、33

2. -p 选项
使用该选项之后xargs并不会马上执行其后面的命令，而是输出即将要执行的完整的命令(包括命令以及传递给命令的命令行参数)，询问是否执行，输入 y 才继续执行，否则不执行。这种方式可以清楚的看到执行的命令是什么样子，也就是xargs传递给命令的参数是什么，例如：
\bashinline{echo '11@22@33' | xargs -p -d '@'  echo }
输出：
\begin{bash}
echo 11 22 33
 ?...y      ==>这里询问是否执行命令 echo 11 22 33 输入y并回车，则显示执行结果，否则不执行
 11 22 33   ==>执行结果
\end{bash}
3. -n 选项
该选项表示将xargs生成的命令行参数，每次传递几个参数给其后面的命令执行，例如如果xargs从标准输入中读入内容，然后以分隔符分割之后生成的命令行参数有10个，使用 -n 3 之后表示一次传递给xargs后面的命令是3个参数，因为一共有10个参数，所以要执行4次，才能将参数用完。例如：

\bashinline{echo '11@22@33@44@55@66@77@88@99@00' | xargs -d '@' -n 3 echo }
输出结果：
\begin{bash}
11 22 33
44 55 66
77 88 99
00
\end{bash}
等价于：
\begin{bash}
echo 11 22 33
echo 44 55 66
echo 77 88 99
echo 00
\end{bash}
实际上运行了4次，每次传递3个参数，最后还剩一个，就直接传递一个参数。

4. -E 选项，有的系统的xargs版本可能是-e  eof-str
该选项指定一个字符串，当xargs解析出多个命令行参数的时候，如果搜索到-e指定的命令行参数，则只会将-e指定的命令行参数之前的参数(不包括-e指定的这个参数)传递给xargs后面的命令\\
\bashinline{echo '11 22 33' | xargs -E '33' echo }
输出：11 22

可以看到正常情况下有3个命令行参数 11、22、33 由于使用了-E '33' 表示在将命令行参数 33 之前的参数传递给执行的命令，33本身不传递。等价于 echo 11 22 这里-E实际上有搜索的作用，表示只取xargs读到的命令行参数前面的某些部分给命令执行。

\textcolor{red}{注意：-E只有在xargs不指定-d的时候有效，如果指定了-d则不起作用，而不管-d指定的是什么字符，空格也不行。}

\bashinline{echo '11 22 33' | xargs -d ' ' -E '33' echo}  => 输出 11 22 33\\

\bashinline{echo '11@22@33@44@55@66@77@88@99@00 aa 33 bb' | xargs -E '33' -d '@' -p  echo} 
\begin{bash}
echo 11 22 33 44 55 66 77 88 99 00 aa 33 bb
 ?...y
    11 22 33 44 55 66 77 88 99 00 aa 33 bb

\end{bash}
-0 选项表示以 '$\textbackslash 0$' 为分隔符，一般与find结合使用

\bashinline{find . -name "*.txt"}
输出：
\begin{Textcode}
./2.txt
./3.txt
./1.txt     => 默认情况下find的输出结果是每条记录后面加上换行，也就是每条记录是一个新行
\end{Textcode}
\bashinline{find . -name "*.txt" -print0}
输出：
\begin{Textcode}
./2.txt./3.txt./1.txt     => 加上 -print0 参数表示find输出的每条结果后面加上 '\0' 而不是换行
\end{Textcode}
\bashinline{find . -name "*.txt" -print0 | xargs -0 echo }
输出：
\begin{bash}
./2.txt ./3.txt ./1.txt
\end{bash}
\bashinline{find . -name "*.txt" -print0 | xargs -d '\0' echo }
输出：
\bashinline{./2.txt ./3.txt ./1.txt}

xargs的 -0 和 -d '$\textbackslash0$' 表示其从标准输入中读取的内容使用 '$\textbackslash 0$' 来分割，由于 find 的结果是使用 '$\textbackslash 0$' 分隔的，所以xargs使用 '$\textbackslash0$' 将 find的结果分隔之后得到3个参数： ./2.txt ./3.txt ./1.txt  注意中间是有空格的。上面的结果就等价于 echo ./2.txt ./3.txt ./1.txt

实际上使用xargs默认的空白分隔符也是可以的  find . -name "*.txt"  | xargs  echo   因为换行符也是xargs的默认空白符的一种。find命令如果不加-print0其搜索结果的每一条字符串后面实际上是加了换行。
\section{unzip}
unzip 选项 参数\\
\begin{itemize}
\item -c：将解压缩的结果显示到屏幕上，并对字符做适当的转换；
\item -f：更新现有的文件；
\item -l：显示压缩文件内所包含的文件；
\item -p：与-c参数类似，会将解压缩的结果显示到屏幕上，但不会执行任何的转换；
\item -t：检查压缩文件是否正确；
\item -u：与-f参数类似，但是除了更新现有的文件外，也会将压缩文件中的其他文件解压缩到目录中；
\item -v：执行时显示详细的信息；
\item -z：仅显示压缩文件的备注文字；
\item -a：对文本文件进行必要的字符转换；
\item -b：不要对文本文件进行字符转换；
\item -C：压缩文件中的文件名称区分大小写；
\item -j：不处理压缩文件中原有的目录路径；
\item -L：将压缩文件中的全部文件名改为小写；
\item -M：将输出结果送到more程序处理；
\item -n：解压缩时不要覆盖原有的文件；
\item -o：不必先询问用户，unzip执行后覆盖原有的文件；
\item -P<密码>：使用zip的密码选项；
\item -q：执行时不显示任何信息；
\item -s：将文件名中的空白字符转换为底线字符；
\item -V：保留VMS的文件版本信息；
\item -X：解压缩时同时回存文件原来的UID/GID；
\item -d<目录>：指定文件解压缩后所要存储的目录；
\item -x<文件>：指定不要处理.zip压缩文件中的哪些文件；
\item -Z：unzip-Z等于执行zipinfo指令。
\end{itemize}
解压压缩文件filename.zip中某一个文件test1/1.jpg到当前目录:\\*\bashinline{unzip filename.zip "test/1.jpg" -d ~/}\\*
查看test.zip目录：\bashinline{unzip -v test.zip}\\*
将test.zip目录中文件解压到tmp，覆盖存在的同名文件：\bashinline{unzip -o test.zip -d tmp/}
